/****************************************************************************\
*                                                                            *
*  Copyright 2008 The CAnt2 Project (http://code.google.com/p/cant2)         *
*                                                                            *
*  Licensed under the Apache License, Version 2.0 (the "License");           *
*  you may not use this file except in compliance with the License.          *
*  You may obtain a copy of the License at                                   *
*                                                                            *
*      http://www.apache.org/licenses/LICENSE-2.0                            *
*                                                                            *
*  Unless required by applicable law or agreed to in writing, software       *
*  distributed under the License is distributed on an "AS IS" BASIS,         *
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
*  See the License for the specific language governing permissions and       *
*  limitations under the License.                                            *
*                                                                            *
\****************************************************************************/

#ifndef INCLUDED_VALUEPTR_H__
#define INCLUDED_VALUEPTR_H__

#include <stdexcept>

// ValuePtr isn't a good name, but it will do for now.
// This type is a strongly owned wrapped pointer.
// Ownership can be transferred with swap to another instance,
// but there is purposefully no way to make a simple copy.
// (Copy could be defined as a deep copy, but that would be problematic)
template < typename T > class ValuePtr
{
public:
    explicit ValuePtr ( T* p = 0 ) : ptr ( p )
    {
    }

    ~ValuePtr()
    {
        delete ptr;
    }

    void Swap ( ValuePtr& other )
    {
        std::swap ( ptr, other.ptr );
    }

    bool IsEmpty() const
    {
        return ptr == 0;
    }

    const T* Get() const
    {
        if ( ptr == 0 ) throw std::runtime_error ( "NULL Dereferenced" );
        return ptr;
    }

    T* Get()
    {
        if ( ptr == 0 ) throw std::runtime_error ( "NULL Dereferenced" );
        return ptr;
    }

    const T* operator ->() const
    {
        if ( ptr == 0 ) throw std::runtime_error ( "NULL Dereferenced" );
        return ptr;
    }

    T* operator ->()
    {
        if ( ptr == 0 ) throw std::runtime_error ( "NULL Dereferenced" );
        return ptr;
    }

private:
    ValuePtr ( const ValuePtr& );
    ValuePtr& operator = ( const ValuePtr& );

private:
    T* ptr;
};

#endif /* #ifndef INCLUDED_VALUEPTR_H__ */

